luci-base: prevent tools.widgets.ZoneSelect tracebacks
authorPaul Donald <[email protected]>
Wed, 23 Apr 2025 12:04:12 +0000 (14:04 +0200)
committerPaul Donald <[email protected]>
Wed, 23 Apr 2025 12:21:41 +0000 (14:21 +0200)
follow-up fix for 0be4ad51a0bea3e1e3e6cd7d646e11ec6c722540

It seems to have been this way for a while, for zone selections
involving the 'any' ('*') choice. firewall forwards.js has no
'this.allowany;' property on the widgets, so the any choice is absent,
leading to a traceback, caused by the 'src' widget, even though
this code block operates on the 'dst' value. Certain combinations of
'src' and 'dst' also triggered tracebacks.

This might not be the correct behaviour for this widget, but it does
prevent tracebacks caused by null values.

Signed-off-by: Paul Donald <[email protected]>
modules/luci-base/htdocs/luci-static/resources/tools/widgets.js

index 4573dca15bbef98f903ada87fb0c8f1bfd218693..221af74cb071667f11de2fa5997c1ebfd63cb3e3 100644 (file)
@@ -189,26 +189,27 @@ var CBIZoneSelect = form.ListValue.extend({
                                                emptyval.parentNode.removeChild(emptyval);
                                }
                                else {
-                                       var anyval = node.querySelector('[data-value="*"]'),
-                                           emptyval = node.querySelector('[data-value=""]');
+                                       const anyval = node.querySelector('[data-value="*"]') || '';
+                                       const emptyval = node.querySelector('[data-value=""]') || '';
 
-                                       if (emptyval == null) {
+                                       if (emptyval == null && anyval) {
                                                emptyval = anyval.cloneNode(true);
                                                emptyval.removeAttribute('display');
                                                emptyval.removeAttribute('selected');
                                                emptyval.setAttribute('data-value', '');
                                        }
 
-                                       if (opt[0].allowlocal)
+                                       if (opt[0]?.allowlocal && emptyval)
                                                L.dom.content(emptyval.querySelector('span'), [
                                                        E('strong', _('Device')), E('span', ' (%s)'.format(_('input')))
                                                ]);
+                                       if (opt[0]?.allowany && anyval && emptyval) {
+                                               L.dom.content(anyval.querySelector('span'), [
+                                                       E('strong', _('Any zone')), E('span', ' (%s)'.format(_('forward')))
+                                               ]);
 
-                                       L.dom.content(anyval.querySelector('span'), [
-                                               E('strong', _('Any zone')), E('span', ' (%s)'.format(_('forward')))
-                                       ]);
-
-                                       anyval.parentNode.insertBefore(emptyval, anyval);
+                                               anyval.parentNode.insertBefore(emptyval, anyval);
+                                       }
                                }
 
                        }, this));